﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using DomainModel;
using Services.Abstract;

namespace Web.Timetable
{
    public partial class Default : BasePage
    {
        public IRingService RingService { get; set; }
        public IGroupService GroupService { get; set; }
        public ITimetableUnitService TimetableUnitService { get; set; }
        public IWorkTypeService WorkTypeService { get; set; }
        public ISubjectService SubjectService { get; set; }
        public IUserService UserService { get; set; }
        public ISemesterService SemesterService { get; set; }
        public IPermissionService PermissionService { get; set; }
        public IStudyYearService StudyYearService { get; set; }

        protected List<Group> Groups = new List<Group>();
        protected StudySemester SelectedSemester;
        protected List<Group> SelectedGroup;
        protected Subject SelectedSubject;
        protected User SelectedTeacher;

        protected new void Page_Load(object sender, EventArgs e)
        {
            SelectMenuItem("NavTimetable");

            InitAdditionalControlsForTimetable();

            Groups = GroupService.GetAll().ToList();

            try
            {
                long semesterId = long.Parse(Request.QueryString["SemesterId"]);
                SelectedSemester = SemesterService.GetById(semesterId);
            }
            catch (ArgumentNullException) { }
            catch (FormatException) { }
            if (SelectedSemester == null)
                SelectedSemester = SemesterService.GetCurrentSemester();

            Group group = null;
            try
            {
                long groupId = long.Parse(Request.QueryString["groupId"]);
                group = GroupService.GetById(groupId);
            }
            catch (ArgumentNullException) { }
            catch (FormatException) { }
            if (group == null)
            {
                SelectedGroup = Groups;
            }
            else
            {
                SelectedGroup = new List<Group> { group };
            }

            try
            {
                long subjectId = long.Parse(Request.QueryString["subjectId"]);
                SelectedSubject = SubjectService.GetById(subjectId);
            }
            catch (ArgumentNullException) { }
            catch (FormatException) { }

            try
            {
                long teacherId = long.Parse(Request.QueryString["teacherId"]);
                SelectedTeacher = UserService.GetById(teacherId);
            }
            catch (ArgumentNullException) { }
            catch (FormatException) { }

            if (!IsPostBack)
            {
                BindDdlSemestersFilter();
                BindDdlGroupsFilter();
                BindDdlSubjectsFilter();
                BindDdlTeachersFilter();

                DdlSemestersFilter.Items.FindByValue(SelectedSemester.Id.ToString()).Selected = true;

                if (SelectedGroup.Count == 1)
                    DdlGroupsFilter.Items.FindByValue(SelectedGroup[0].Id.ToString()).Selected = true;
                else
                    DdlGroupsFilter.Items.FindByValue("0").Selected = true;

                if (SelectedSubject != null)
                    DdlSubjectsFilter.Items.FindByValue(SelectedSubject.Id.ToString()).Selected = true;
                else
                    DdlSubjectsFilter.Items.FindByValue("0").Selected = true;

                if (SelectedTeacher != null)
                    DdlTeachersFilter.Items.FindByValue(SelectedTeacher.Id.ToString()).Selected = true;
                else
                    DdlTeachersFilter.Items.FindByValue("0").Selected = true;

                BindTimetables();

                if (PermissionService.CanCUDTimetableUnits())
                {
                    BindDdlSubjects();
                    BindDdlWorkTypes();
                    BindDdlTeachers();
                    BindDdlGroups();
                }
            }
        }

        private void BindDdlTeachersFilter()
        {
            var teachers = UserService.GetUsers(Role.Teacher).OrderBy(u => u.UserProfile.Fio).ToList();

            var ds = new List<object>
                         {
                             new
                                 {
                                     Id = (long) 0,
                                     Fio = ""
                                 }
                         };

            foreach (var teacher in teachers)
            {
                ds.Add(new
                           {
                               Id = teacher.Id,
                               Fio = teacher.UserProfile.Fio,
                           });
            }

            DdlTeachersFilter.DataSource = ds;
            DdlTeachersFilter.DataValueField = "Id";
            DdlTeachersFilter.DataTextField = "Fio";
            DdlTeachersFilter.DataBind();
        }

        private void BindDdlSubjectsFilter()
        {
            var subjects = SubjectService.GetAll().OrderBy(s => s.Name).ToList();

            var ds = new List<object>
                         {
                             new
                                 {
                                     Id = (long) 0,
                                     Name = "",
                                 }
                         };

            foreach (var subject in subjects)
            {
                ds.Add(new
                {
                    Id = subject.Id,
                    Name = subject.Name,
                });
            }

            DdlSubjectsFilter.DataSource = ds;
            DdlSubjectsFilter.DataValueField = "Id";
            DdlSubjectsFilter.DataTextField = "Name";
            DdlSubjectsFilter.DataBind();
        }

        private void BindDdlGroupsFilter()
        {
            var groups = Groups.OrderBy(g => g.Name).ToList();

            var ds = new List<object>
                         {
                             new
                                 {
                                     Id = (long) 0,
                                     Name = "",
                                 }
                         };

            foreach (var group in groups)
            {
                ds.Add(new
                {
                    Id = group.Id,
                    Name = group.Name,
                });
            }

            DdlGroupsFilter.DataSource = ds;
            DdlGroupsFilter.DataValueField = "Id";
            DdlGroupsFilter.DataTextField = "Name";
            DdlGroupsFilter.DataBind();
        }

        private void BindDdlSemestersFilter()
        {
            var studyYears = StudyYearService.GetAll().OrderBy(sy => sy.BeginDate).ToList();

            var ds = new List<object>();

            foreach (var studyYear in studyYears)
            {
                int semesterNo = 1;
                foreach (var semester in studyYear.StudySemesters)
                {
                    ds.Add(new
                    {
                        Id = semester.Id,
                        Name = studyYear.Name + " (" + semesterNo + "-й семестр)",
                    });
                    semesterNo++;
                }
            }

            DdlSemestersFilter.DataSource = ds;
            DdlSemestersFilter.DataValueField = "Id";
            DdlSemestersFilter.DataTextField = "Name";
            DdlSemestersFilter.DataBind();
        }

        private void BindTimetables()
        {
            string innerHtml = "";

            for (int week = 1; week <= 2; week++)
            {
                innerHtml += "<p>" + string.Format("{0}-я неделя ({1})", week, week == 1 ? "парная" : "непарная") + "</p>";

                innerHtml += "<table class=\"table-bordered timetable\">";

                innerHtml += "<tr>";
                innerHtml += "<th>День</th>";
                innerHtml += "<th>Пара</th>";
                innerHtml += "<th>Время</th>";
                foreach (var group in SelectedGroup)
                {
                    innerHtml += "<th>" + group.Name + "</th>";
                }
                innerHtml += "</tr>";

                for (int day = 1; day <= 6; day++)
                {
                    for (int pairNo = 1; pairNo <= 7; pairNo++)
                    {
                        if (pairNo == 1)
                        {
                            innerHtml += "<tr class='first-pair-row'>";
                        }
                        else
                        {
                            innerHtml += "<tr>";
                        }

                        if (pairNo == 1)
                        {
                            innerHtml += "<td rowspan=" + 7 + ">";

                            switch (day)
                            {
                                case 1:
                                    innerHtml += "Пн";
                                    break;
                                case 2:
                                    innerHtml += "Вт";
                                    break;
                                case 3:
                                    innerHtml += "Ср";
                                    break;
                                case 4:
                                    innerHtml += "Чт";
                                    break;
                                case 5:
                                    innerHtml += "Пт";
                                    break;
                                case 6:
                                    innerHtml += "Сб";
                                    break;
                            }

                            innerHtml += "</td>";
                        }

                        innerHtml += "<td>" + pairNo + "</td>";

                        innerHtml += "<td>";
                        innerHtml += "<span>" + RingService.GetPairBeginTime(pairNo) + "</span>";
                        innerHtml += "<br />";
                        innerHtml += "<span>" + RingService.GetPairEndTime(pairNo) + "</span>";
                        innerHtml += "</td>";

                        foreach (var group in SelectedGroup)
                        {
                            innerHtml += "<td>";

                            TimetableUnit timetableUnit;
                            
                            if (SelectedSubject != null && SelectedTeacher == null)
                                timetableUnit = TimetableUnitService.GetTimetableUnit(SelectedSemester, week, day, pairNo, group, SelectedSubject);
                            else if (SelectedSubject == null && SelectedTeacher != null)
                                timetableUnit = TimetableUnitService.GetTimetableUnit(SelectedSemester, week, day, pairNo, group, SelectedTeacher);
                            else if (SelectedSubject != null && SelectedTeacher != null)
                                timetableUnit = TimetableUnitService.GetTimetableUnit(SelectedSemester, week, day, pairNo, group, SelectedTeacher, SelectedSubject);
                            else
                                timetableUnit = TimetableUnitService.GetTimetableUnit(SelectedSemester, week, day, pairNo, group);
                            if (timetableUnit != null)
                            {
                                innerHtml += timetableUnit.Subject.ShortName;

                                innerHtml += "<br />";
                                innerHtml += "<small>(" + WorkTypeService.GetWorkTypeName(timetableUnit.WorkType) + ")</small>";
                                innerHtml += "<br />";
                                if (timetableUnit.Teacher != null)
                                {
                                    innerHtml += "<small>" + timetableUnit.Teacher.UserProfile.Fio + "</small>";
                                    innerHtml += "<br />";
                                }
                                innerHtml += "<small>" + timetableUnit.Room + "</small>";
                            }

                            if (PermissionService.CanCUDTimetableUnits())
                            {
                                if (timetableUnit == null)
                                {
                                    innerHtml += string.Format("<a class=\"timetable-unit-button\" onclick=\"FillEditTimetableUnitForm('{0}','{1}','{2}','{3}','{4}');\"></a>", week, day, pairNo, group.Id, 0);
                                }
                                else
                                {
                                    if (PermissionService.CanCUDTimetableUnit(timetableUnit))
                                    {
                                        innerHtml += string.Format("<a class=\"timetable-unit-button\" onclick=\"FillEditTimetableUnitForm('{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}','{8}');\"></a>", week, day, pairNo, group.Id, timetableUnit.Id, timetableUnit.Subject.Id, timetableUnit.WorkType.ToString(), timetableUnit.Teacher == null ? 1 : timetableUnit.Teacher.Id, timetableUnit.Room);
                                    }
                                }
                            }

                            innerHtml += "</td>";
                        }

                        innerHtml += "</tr>";
                    }
                }

                innerHtml += "</table>";
            }

            Timetables.InnerHtml = innerHtml;
        }

        private void BindDdlGroups()
        {
            DdlGroups.DataSource = GroupService.GetAll().OrderBy(g => g.Name);
            DdlGroups.DataValueField = "Id";
            DdlGroups.DataTextField = "Name";
            DdlGroups.DataBind();
        }

        private void BindDdlSubjects()
        {
            DdlSubjects.DataSource = SubjectService.GetAll().OrderBy(s => s.Name);
            DdlSubjects.DataValueField = "Id";
            DdlSubjects.DataTextField = "Name";
            DdlSubjects.DataBind();
        }

        private void BindDdlWorkTypes()
        {
            DdlWorkTypes.Items.Clear();
            if (User.IsInRole(Role.TrainingDivisionWorker.ToString()) || User.IsInRole(Role.Admin.ToString()))
            {
                DdlWorkTypes.Items.Add(new ListItem(WorkTypeService.GetWorkTypeName(WorkType.Lection), WorkType.Lection.ToString()));
                DdlWorkTypes.Items.Add(new ListItem(WorkTypeService.GetWorkTypeName(WorkType.Lab), WorkType.Lab.ToString()));
                DdlWorkTypes.Items.Add(new ListItem(WorkTypeService.GetWorkTypeName(WorkType.Practical), WorkType.Practical.ToString()));
            }
            DdlWorkTypes.Items.Add(new ListItem(WorkTypeService.GetWorkTypeName(WorkType.Consultation), WorkType.Consultation.ToString()));
        }

        private void BindDdlTeachers()
        {
            var ds = new List<object>();

            if (User.IsInRole(Role.TrainingDivisionWorker.ToString()) || User.IsInRole(Role.Admin.ToString()))
            {
                var teachers = UserService.GetUsers(Role.Teacher).OrderBy(t => t.UserProfile.Fio);

                foreach (var teacher in teachers)
                {
                    ds.Add(new
                               {
                                   Id = teacher.Id,
                                   Fio = teacher.UserProfile.Fio,
                               });
                }
            }
            else
            {
                User currentUser = UserService.GetUserByLogin(User.Identity.Name);
                ds.Add(new
                           {
                               Id = currentUser.Id,
                               Fio = currentUser.UserProfile.Fio,
                           });
            }

            DdlTeachers.DataSource = ds;
            DdlTeachers.DataValueField = "Id";
            DdlTeachers.DataTextField = "Fio";
            DdlTeachers.DataBind();
        }

        private void InitAdditionalControlsForTimetable()
        {
            InitAdditionalControls();
            ScriptManager.RegisterStartupScript(Page, GetType(), "InitAdditionalControlsForTimetable", "InitAdditionalControlsForTimetable();", true);
        }

        protected void BtnDeleteTimetableUnit_OnClick(object sender, EventArgs e)
        {
            try
            {
                TimetableUnit timetableUnit = null;

                long timetableUnitId = long.Parse(FieldTimetableUnitId.Value);
                if (timetableUnitId > 0)
                    timetableUnit = TimetableUnitService.GetById(timetableUnitId);

                if (timetableUnit != null)
                {
                    TimetableUnitService.Delete(timetableUnit);
                }
            }
            catch (Exception ex)
            {
                ShowFormError(EditTimetableUnitFormError.ClientID, ex.Message);
                ScriptManager.RegisterStartupScript(Page, GetType(), "ShowEditTimetableUnitForm", "ShowEditTimetableUnitForm('Изменить в расписании');", true);
            }

            BindTimetables();
        }

        protected void BtnSaveTimetableUnit_OnClick(object sender, EventArgs e)
        {
            try
            {
                int week = int.Parse(TbWeekNo.Text);
                int day = int.Parse(TbDayNo.Text);
                int pairNo = int.Parse(TbPairNo.Text);
                Group group = GroupService.GetById(long.Parse(DdlGroups.SelectedValue));
                Subject subject = SubjectService.GetById(long.Parse(DdlSubjects.SelectedValue));
                WorkType workType = WorkTypeService.GetWorkTypeByName(DdlWorkTypes.SelectedItem.Text);
                User teacher = UserService.GetById(long.Parse(DdlTeachers.SelectedValue));
                string room = TbRoom.Text;

                TimetableUnit timetableUnit = null;

                long timetableUnitId = long.Parse(FieldTimetableUnitId.Value);
                if (timetableUnitId > 0)
                    timetableUnit = TimetableUnitService.GetById(timetableUnitId);

                if (timetableUnit == null)
                {
                    timetableUnit = new TimetableUnit(SelectedSemester, week, day, pairNo, group, subject, teacher, workType, room);
                }
                else
                {
                    timetableUnit.Week = week;
                    timetableUnit.Day = day;
                    timetableUnit.PairNo = pairNo;
                    timetableUnit.Group = group;
                    timetableUnit.Subject = subject;
                    timetableUnit.WorkType = workType;
                    timetableUnit.Teacher = teacher;
                    timetableUnit.Room = room;
                }

                TimetableUnitService.SaveOrUpdate(timetableUnit);
            }
            catch (Exception ex)
            {
                ShowFormError(EditTimetableUnitFormError.ClientID, ex.Message);
                ScriptManager.RegisterStartupScript(Page, GetType(), "ShowEditTimetableUnitForm", "ShowEditTimetableUnitForm('Изменить в расписании');", true);
            }

            BindTimetables();
        }

        protected void DdlGroupsFilter_OnSelectedIndexChanged(object sender, EventArgs e)
        {
            string url = "/Timetable.aspx?";

            var qs = HttpUtility.ParseQueryString(Request.Url.Query);

            if (qs.Count > 0 && qs["GroupId"] != null)
            {
                if (DdlGroupsFilter.SelectedValue != "0")
                    qs.Set("GroupId", DdlGroupsFilter.SelectedValue);
                else
                    qs.Remove("GroupId");
            }
            else
            {
                if (DdlGroupsFilter.SelectedValue != "0")
                    qs.Add("GroupId", DdlGroupsFilter.SelectedValue);
            }

            url += qs + "&";

            Response.Redirect(url);
        }

        protected void DdlSemestersFilter_OnSelectedIndexChanged(object sender, EventArgs e)
        {
            string url = "/Timetable.aspx?";

            var qs = HttpUtility.ParseQueryString(Request.Url.Query);

            if (qs.Count > 0 && qs["SemesterId"] != null)
            {
                if (DdlSemestersFilter.SelectedValue != "0")
                    qs.Set("SemesterId", DdlSemestersFilter.SelectedValue);
                else
                    qs.Remove("SemesterId");
            }
            else
            {
                if (DdlSemestersFilter.SelectedValue != "0")
                    qs.Add("SemesterId", DdlSemestersFilter.SelectedValue);
            }

            url += qs + "&";

            Response.Redirect(url);
        }

        protected void DdlSubjectsFilter_OnSelectedIndexChanged(object sender, EventArgs e)
        {
            string url = "/Timetable.aspx?";

            var qs = HttpUtility.ParseQueryString(Request.Url.Query);

            if (qs.Count > 0 && qs["SubjectId"] != null)
            {
                if (DdlSubjectsFilter.SelectedValue != "0")
                    qs.Set("SubjectId", DdlSubjectsFilter.SelectedValue);
                else
                    qs.Remove("SubjectId");
            }
            else
            {
                if (DdlSubjectsFilter.SelectedValue != "0")
                    qs.Add("SubjectId", DdlSubjectsFilter.SelectedValue);
            }

            url += qs + "&";

            Response.Redirect(url);
        }

        protected void DdlTeachersFilter_OnSelectedIndexChanged(object sender, EventArgs e)
        {
            string url = "/Timetable.aspx?";

            var qs = HttpUtility.ParseQueryString(Request.Url.Query);

            if (qs.Count > 0 && qs["TeacherId"] != null)
            {
                if (DdlTeachersFilter.SelectedValue != "0")
                    qs.Set("TeacherId", DdlTeachersFilter.SelectedValue);
                else
                    qs.Remove("TeacherId");
            }
            else
            {
                if (DdlTeachersFilter.SelectedValue != "0")
                    qs.Add("TeacherId", DdlTeachersFilter.SelectedValue);
            }

            url += qs + "&";

            Response.Redirect(url);
        }
    }
}